package com.hpeng.util;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class GenericDaoImpl<T, PK extends Serializable> implements
		GenericDao<T, PK> {

	@Resource
	private HibernateTemplate hibernateTemplate;

	private Class<T> persistentClass;

	@SuppressWarnings("unchecked")
	public GenericDaoImpl() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public GenericDaoImpl(Class<T> persistentClass) {
		this.persistentClass = persistentClass;
	}

	@SuppressWarnings("unchecked")
	public T get(PK id) {
		return (T) hibernateTemplate.get(this.persistentClass, id);
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		return hibernateTemplate.loadAll(this.persistentClass);
	}
	
	@SuppressWarnings("unchecked")
	public T save(T object) {
		return (T) get((PK)hibernateTemplate.save(object));
	}
	
	@SuppressWarnings("unchecked")
	public T update(T object) {
		return (T) hibernateTemplate.merge(object);
	}

	public void saveAll(List<T> ts) {
		hibernateTemplate.saveOrUpdateAll(ts);
	}

	public void remove(PK id) {
		hibernateTemplate.delete(this.get(id));
	}

	@SuppressWarnings("unchecked")
	public List<T> getByHql(String hql) {
		return hibernateTemplate.find(hql);
	}

	public Long count() {
		DetachedCriteria criteria = DetachedCriteria.forClass(this.persistentClass);
		criteria.setProjection(Projections.rowCount());
		Object ret = hibernateTemplate.findByCriteria(criteria).get(0);
		return (ret instanceof Long) ? (Long) ret : (Integer) ret;
	}

	@SuppressWarnings("unchecked")
	public Long countByHql(String hql) {
		List<Long> list = hibernateTemplate.find(hql);
		Long count = list.get(0);
		return count;
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll(int firstResult, int maxResults) {
		DetachedCriteria criteria = DetachedCriteria
				.forClass(this.persistentClass);
		return hibernateTemplate.findByCriteria(criteria, firstResult,
				maxResults);
	}

	@SuppressWarnings("unchecked")
	public List<Object[]> queryByhql(String hql, int firstResult, int maxResults) {
		return hibernateTemplate.getSessionFactory().openSession().createQuery(
				hql).setFirstResult(firstResult).setMaxResults(maxResults)
				.list();
	}

	public Pagination<T> getPagination(final String hql, final Object[] values,
			final int pageNumber) {
		return getPagination(hql, values, pageNumber, Constant.PAGE_SIZE);
	}
	
	public Pagination<T> getPagination (String[] hql, Object[] values,int pageNumber) {
		Pagination<T> pagination = null;
		StringBuffer sb = new StringBuffer();
		try {
			for(String str : hql){
				sb.append(str);
		}
		pagination = getPagination(sb.toString(), values, pageNumber, Constant.PAGE_SIZE);	
		} catch (Exception e) {
			e.printStackTrace();
		}
		return pagination;
	}

	@SuppressWarnings("unchecked")
	public Pagination<T> getPagination(final String hql, final Object[] values,
			final int pageNumber, final int pageSize) {
		return (Pagination<T>) hibernateTemplate.execute(new HibernateCallback() {
					public Object doInHibernate(Session session) throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						if (values != null) {
							for (int i = 0; i < values.length; i++) {
								query.setParameter(i, values[i]);
							}
						}
						int count = query.list().size();
						Pagination<T> p = new Pagination(pageNumber, pageSize, count);
System.out.println("p.getCount()-->"+p.getCount());
System.out.println("p.getFirstResult()-->"+p.getFirstResult());
System.out.println("p.getMaxResult()-->"+p.getMaxResult());
						query.setFirstResult(p.getFirstResult());
						query.setMaxResults(p.getMaxResult());
						p.setDataList(query.list());
						return p;
					}
				});
	}
	
	@SuppressWarnings("unchecked")
	public List<T> getBySql(final String sql , final Class T){
		return (List<T>)hibernateTemplate.executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				return session.createSQLQuery(sql).addEntity(T.getClass()).list();
			}
		});
	}
	
	public boolean executeBySql(final String sql) throws Exception {
		return ((Integer)hibernateTemplate.execute(new HibernateCallback(){
			public Object doInHibernate(org.hibernate.Session session)
					throws HibernateException, SQLException {
				return session.createSQLQuery(sql).executeUpdate();
			}
		})).intValue()>0?true:false;
	}
	
	public void removeAllByIds(PK... ids) {
		Collection<T> entities = new ArrayList<T>();
		T t = null;
		for (PK id : ids) {
			t = get(id);
			if (t != null) {
				entities.add(t);
			}
		}
		hibernateTemplate.deleteAll(entities);
	}
	
	public void removeAllByEntities(Collection<T> entities) {
		hibernateTemplate.deleteAll(entities);
	}
	/**
	 * 保存和添加
	 * @param entity
	 */
	public void saveOrUpdate(T entity) {
		hibernateTemplate.saveOrUpdate(entity);
	}
	
	/**
	 * 根据对象删除
	 * @param entitiy
	 */
	public void delete(T entitiy){
		hibernateTemplate.delete(entitiy);
	}
	
	/**
	 * 查找指定PK的一个实体类对象
	 * 
	 * @param entityClass
	 *            实体Class
	 * @param id
	 *            实体PK
	 * @return 实体对象
	 */
	@SuppressWarnings("unchecked")
	public T findEnityById(Class<T> entityClass, PK id) {
		return (T) hibernateTemplate.get(entityClass, id);
	}
}
